package com.freesia.desensization.util;

import cn.hutool.core.util.CharUtil;
import cn.hutool.core.util.StrUtil;
import com.freesia.desensization.constant.DesensitizedType;
import com.freesia.util.UEmpty;

/**
 * @author Evad.Wu
 * @Description 自定义数据脱敏 工具类
 * @date 2023-03-12
 */
public class UDesensitized {
    public static String desensitized(CharSequence str, DesensitizedType... desensitizedTypes) {
        if (UEmpty.isEmpty(str)) {
            return StrUtil.EMPTY;
        }
        String original = (String) str;
        String newStr = String.valueOf(original);
        for (DesensitizedType strategy : desensitizedTypes) {
            switch (strategy) {
                case CHINESE_NAME -> newStr = UDesensitized.chineseName(original);
                case EURO_AMERICAN_NAME -> newStr = UDesensitized.euroAmericanName(original);
                case ID_CARD -> newStr = UDesensitized.idCardNum(original, 1, 2);
                case FIXED_PHONE -> newStr = UDesensitized.fixedPhone(original);
                case MOBILE_PHONE -> newStr = UDesensitized.mobilePhone(original);
                case ADDRESS -> newStr = UDesensitized.address(original, 8);
                case EMAIL -> newStr = UDesensitized.email(original);
                case PASSWORD -> newStr = UDesensitized.password(original);
                case CAR_LICENSE -> newStr = UDesensitized.carLicense(original);
                case BANK_CARD -> newStr = UDesensitized.bankCard(original);
                default -> {
                    return original;
                }
            }
            // 如果已经经过某个脱敏规则处理被修改，则不再处理之后的规则
            if (!newStr.equalsIgnoreCase(original)) {
                return newStr;
            }
        }
        return newStr;
    }

    /**
     * 【用户id】不对外提供userId
     *
     * @return 脱敏后的主键
     */
    public static Long userId() {
        return 0L;
    }

    /**
     * 【中文姓名】只显示第一个汉字，其他隐藏为2个星号，比如：李**
     *
     * @param fullName 姓名
     * @return 脱敏后的姓名
     */
    public static String chineseName(String fullName) {
        if (StrUtil.isBlank(fullName)) {
            return StrUtil.EMPTY;
        }
        return StrUtil.hide(fullName, 1, fullName.length());
    }

    /**
     * 【身份证号】前1位 和后2位
     *
     * @param idCardNum 身份证
     * @param front     保留：前面的front位数；从1开始
     * @param end       保留：后面的end位数；从1开始
     * @return 脱敏后的身份证
     */
    public static String idCardNum(String idCardNum, int front, int end) {
        //身份证不能为空
        if (StrUtil.isBlank(idCardNum)) {
            return StrUtil.EMPTY;
        }
        //需要截取的长度不能大于身份证号长度
        if ((front + end) > idCardNum.length()) {
            return StrUtil.EMPTY;
        }
        //需要截取的不能小于0
        if (front < 0 || end < 0) {
            return StrUtil.EMPTY;
        }
        return StrUtil.hide(idCardNum, front, idCardNum.length() - end);
    }

    /**
     * 【固定电话 前四位，后两位
     *
     * @param num 固定电话
     * @return 脱敏后的固定电话；
     */
    public static String fixedPhone(String num) {
        if (StrUtil.isBlank(num)) {
            return StrUtil.EMPTY;
        }
        return StrUtil.hide(num, 4, num.length() - 2);
    }

    /**
     * 【手机号码】前三位，后4位，其他隐藏，比如135****2210
     *
     * @param num 移动电话；
     * @return 脱敏后的移动电话；
     */
    public static String mobilePhone(String num) {
        if (StrUtil.isBlank(num)) {
            return StrUtil.EMPTY;
        }
        return StrUtil.hide(num, 3, num.length() - 4);
//        if (StrUtil.isBlank(num)) {
//            return "";
//        }
//        return num.replaceAll("(\\d{3})\\d{5}(\\d{3})", "$1**#**$2");
    }

    /**
     * 【地址】只显示到地区，不显示详细地址，比如：北京市海淀区****
     *
     * @param address       家庭住址
     * @param sensitiveSize 敏感信息长度
     * @return 脱敏后的家庭地址
     */
    public static String address(String address, int sensitiveSize) {
        if (StrUtil.isBlank(address)) {
            return StrUtil.EMPTY;
        }
        int length = address.length();
        return StrUtil.hide(address, length - sensitiveSize, length);
    }

    /**
     * 【电子邮箱】邮箱前缀仅显示第一个字母，前缀其他隐藏，用星号代替，@及后面的地址显示，比如：d**@126.com
     *
     * @param email 邮箱
     * @return 脱敏后的邮箱
     */
    public static String email(String email) {
        if (StrUtil.isBlank(email)) {
            return StrUtil.EMPTY;
        }
        int index = StrUtil.indexOf(email, '@');
        if (index <= 1) {
            return email;
        }
        return StrUtil.hide(email, 1, index);
    }

    /**
     * 【密码】密码的全部字符都用*代替，比如：******
     *
     * @param password 密码
     * @return 脱敏后的密码
     */
    public static String password(String password) {
        if (StrUtil.isBlank(password)) {
            return StrUtil.EMPTY;
        }
        return StrUtil.repeat('*', password.length());
    }

    /**
     * 【中国车牌】车牌中间用*代替
     * eg1：null       -》 ""
     * eg1：""         -》 ""
     * eg3：苏D40000   -》 苏D4***0
     * eg4：陕A12345D  -》 陕A1****D
     * eg5：京A123     -》 京A123     如果是错误的车牌，不处理
     *
     * @param carLicense 完整的车牌号
     * @return 脱敏后的车牌
     */
    public static String carLicense(String carLicense) {
        if (StrUtil.isBlank(carLicense)) {
            return StrUtil.EMPTY;
        }
        // 普通车牌
        if (carLicense.length() == 7) {
            carLicense = StrUtil.hide(carLicense, 3, 6);
        } else if (carLicense.length() == 8) {
            // 新能源车牌
            carLicense = StrUtil.hide(carLicense, 3, 7);
        }
        return carLicense;
    }

    /**
     * 银行卡号脱敏
     * eg: 1101 **** **** **** 3256
     *
     * @param bankCardNo 银行卡号
     * @return 脱敏之后的银行卡号
     * @since 5.6.3
     */
    public static String bankCard(String bankCardNo) {
        if (StrUtil.isBlank(bankCardNo)) {
            return bankCardNo;
        }
        bankCardNo = StrUtil.trim(bankCardNo);
        if (bankCardNo.length() < 9) {
            return bankCardNo;
        }

        final int length = bankCardNo.length();
        final int midLength = length - 8;
        final StringBuilder buf = new StringBuilder();

        buf.append(bankCardNo, 0, 4);
        for (int i = 0; i < midLength; ++i) {
            if (i % 4 == 0) {
                buf.append(CharUtil.SPACE);
            }
            buf.append('*');
        }
        buf.append(CharUtil.SPACE).append(bankCardNo, length - 4, length);
        return buf.toString();
    }

    /**
     * 欧美人名保留第一个名
     *
     * @param name 名字
     * @return 脱敏后的名字
     */
    public static String euroAmericanName(String name) {
        if (StrUtil.isBlank(name)) {
            return name;
        }
        name = StrUtil.trim(name);
        // 第一个空格之后都脱敏处理
        String[] nameSplit = name.split(" ");
        if (nameSplit.length > 1) {
            StringBuilder sb = new StringBuilder();
            for (int i = 0, len = nameSplit.length - 1; i < len; i++) {
                sb.append("*".repeat(nameSplit[i].length()));
                if (i != len - 1) {
                    sb.append("*");
                }
            }
            sb.append(" ").append(nameSplit[nameSplit.length - 1]);
            return sb.toString();
        }
        return name;
    }
}
